home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gstype42.c < prev    next >
C/C++ Source or Header  |  1997-03-13  |  13KB  |  440 lines

  1. /* Copyright (C) 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gstype42.c */
  20. /* Type 42 (TrueType) font library routines */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsstruct.h"
  25. #include "gsccode.h"
  26. #include "gsmatrix.h"
  27. #include "gxfixed.h"            /* for gxpath.h */
  28. #include "gxpath.h"
  29. #include "gxfont.h"
  30. #include "gxfont42.h"
  31. #include "gxistate.h"
  32.  
  33. /*
  34.  * This Type 42 / TrueType rasterizer is about as primitive as it can be
  35.  * and still produce useful output.  Here are some things it doesn't handle:
  36.  *    - left side bearings;
  37.  * and, of course, instructions (hints).
  38.  */
  39.  
  40. /* Structure descriptor */
  41. public_st_gs_font_type42();
  42.  
  43. /* Set up a pointer to a substring of the font data. */
  44. /* Free variables: pfont, string_proc. */
  45. #define access(base, length, vptr)\
  46.   do {\
  47.     code = (*string_proc)(pfont, (ulong)(base), length, &vptr);\
  48.     if ( code < 0 ) return code;\
  49.   } while (0)
  50.  
  51. /* Get 2- or 4-byte quantities from a table. */
  52. #define u16(p) (((uint)((p)[0]) << 8) + (p)[1])
  53. #define s16(p) (int)((u16(p) ^ 0x8000) - 0x8000)
  54. #define u32(p) (((ulong)u16(p) << 16) + u16((p) + 2))
  55. #define s32(p) (long)((u32(p) ^ 0x80000000) - 0x80000000)
  56.  
  57. /* Define the default implementation for getting the outline data for */
  58. /* a glyph, using indexToLocFormat and the loca and glyf tables. */
  59. /* Set pglyph->data = 0 if the glyph is empty. */
  60. private int
  61. default_get_outline(gs_font_type42 *pfont, uint glyph_index,
  62.   gs_const_string *pglyph)
  63. {    int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
  64.       pfont->data.string_proc;
  65.     const byte *ploca;
  66.     ulong glyph_start;
  67.     uint glyph_length;
  68.     int code;
  69.  
  70.     if ( pfont->data.indexToLocFormat )
  71.       { access(pfont->data.loca + glyph_index * 4, 8, ploca);
  72.         glyph_start = u32(ploca);
  73.         glyph_length = u32(ploca + 4) - glyph_start;
  74.       }
  75.     else
  76.       { access(pfont->data.loca + glyph_index * 2, 4, ploca);
  77.         glyph_start = (ulong)u16(ploca) << 1;
  78.         glyph_length = ((ulong)u16(ploca + 2) << 1) - glyph_start;
  79.       }
  80.     pglyph->size = glyph_length;
  81.     if ( glyph_length == 0 )
  82.       pglyph->data = 0;
  83.     else
  84.       access(pfont->data.glyf + glyph_start, glyph_length, pglyph->data);
  85.     return 0;
  86. }
  87.  
  88. /* Initialize the cached values in a Type 42 font. */
  89. /* Note that this initializes get_outline as well. */
  90. int
  91. gs_type42_font_init(gs_font_type42 *pfont)
  92. {    int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
  93.       pfont->data.string_proc;
  94.     const byte *OffsetTable;
  95.     uint numTables;
  96.     const byte *TableDirectory;
  97.     uint i;
  98.     int code;
  99.     byte head_box[8];
  100.  
  101.     access(0, 12, OffsetTable);
  102.     { static const byte version1_0[4] = {0,1,0,0};
  103.       if ( memcmp(OffsetTable, version1_0, 4) )
  104.         return_error(gs_error_invalidfont);
  105.     }
  106.     numTables = u16(OffsetTable + 4);
  107.     access(12, numTables * 16, TableDirectory);
  108.     for ( i = 0; i < numTables; ++i )
  109.       { const byte *tab = TableDirectory + i * 16;
  110.         ulong offset = u32(tab + 8);
  111.         if ( !memcmp(tab, "glyf", 4) )
  112.           pfont->data.glyf = offset;
  113.         else if ( !memcmp(tab, "head", 4) )
  114.           { const byte *head;
  115.         access(offset, 54, head);
  116.         pfont->data.unitsPerEm = u16(head + 18);
  117.         memcpy(head_box, head + 36, 8);
  118.         pfont->data.indexToLocFormat = u16(head + 50);
  119.           }
  120.         else if ( !memcmp(tab, "hhea", 4) )
  121.           { const byte *hhea;
  122.         access(offset, 36, hhea);
  123.         pfont->data.numLongMetrics = u16(hhea + 34);
  124.           }
  125.         else if ( !memcmp(tab, "hmtx", 4) )
  126.           pfont->data.hmtx = offset,
  127.           pfont->data.hmtx_length = (uint)u32(tab + 12);
  128.         else if ( !memcmp(tab, "loca", 4) )
  129.           pfont->data.loca = offset;
  130.       }
  131.     /* If the font doesn't have a valid FontBBox, */
  132.     /* compute one from the 'head' information. */
  133.     if ( pfont->FontBBox.p.x >= pfont->FontBBox.q.x ||
  134.          pfont->FontBBox.p.y >= pfont->FontBBox.q.y
  135.        )
  136.       { float upem = pfont->data.unitsPerEm;
  137.         pfont->FontBBox.p.x = s16(head_box) / upem;
  138.         pfont->FontBBox.p.y = s16(head_box + 2) / upem;
  139.         pfont->FontBBox.q.x = s16(head_box + 4) / upem;
  140.         pfont->FontBBox.q.y = s16(head_box + 6) / upem;
  141.       }
  142.     pfont->data.get_outline = default_get_outline;
  143.     return 0;
  144. }
  145.  
  146. /* Get the metrics of a glyph. */
  147. int
  148. gs_type42_get_metrics(gs_font_type42 *pfont, uint glyph_index,
  149.   float psbw[4])
  150. {    int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
  151.       pfont->data.string_proc;
  152.     float scale = pfont->data.unitsPerEm;
  153.     uint widthx;
  154.     int lsbx;
  155.     int code;
  156.  
  157.     { uint num_metrics = pfont->data.numLongMetrics;
  158.       const byte *hmetrics;
  159.       if ( glyph_index < num_metrics )
  160.         { access(pfont->data.hmtx + glyph_index * 4, 4, hmetrics);
  161.           widthx = u16(hmetrics);
  162.           lsbx = s16(hmetrics + 2);
  163.         }
  164.       else
  165.         { uint offset = pfont->data.hmtx + (num_metrics - 1) * 4;
  166.           const byte *lsb;
  167.           access(offset, 4, hmetrics);
  168.           widthx = u16(hmetrics);
  169.           offset += 4 + (glyph_index - num_metrics) * 2;
  170.           if ( offset >= pfont->data.hmtx_length )
  171.         offset = pfont->data.hmtx_length - 2;
  172.           access(offset, 2, lsb);
  173.           lsbx = s16(lsb);
  174.         }
  175.     }
  176.     psbw[0] = lsbx / scale;
  177.     psbw[1] = 0;
  178.     psbw[2] = widthx / scale;
  179.     psbw[3] = 0;
  180.     return 0;
  181. }
  182.  
  183. /* Define the bits in the glyph flags. */
  184. #define gf_OnCurve 1
  185. #define gf_xShort 2
  186. #define gf_yShort 4
  187. #define gf_Repeat 8
  188. #define gf_xPos 16    /* xShort */
  189. #define gf_xSame 16    /* !xShort */
  190. #define gf_yPos 32    /* yShort */
  191. #define gf_ySame 32    /* !yShort */
  192.  
  193. /* Define the bits in the component glyph flags. */
  194. #define cg_argsAreWords 1
  195. #define cg_argsAreXYValues 2
  196. #define cg_haveScale 8
  197. #define cg_moreComponents 32
  198. #define cg_haveXYScale 64
  199. #define cg_have2x2 128
  200.  
  201. /* Forward references */
  202. private int append_outline(P4(uint glyph_index, const gs_matrix_fixed *pmat,
  203.                   gx_path *ppath, gs_font_type42 *pfont));
  204.  
  205. /* Append a TrueType outline to a path. */
  206. /* Note that this does not append the final moveto for the width. */
  207. int
  208. gs_type42_append(uint glyph_index, gs_imager_state *pis,
  209.   gx_path *ppath, const gs_log2_scale_point *pscale, bool charpath_flag,
  210.   int paint_type, gs_font_type42 *pfont)
  211. {    /*
  212.      * This is where we should do something about the l.s.b., but I
  213.      * can't figure out from the TrueType documentation what it should
  214.      * be.
  215.      */
  216.     return append_outline(glyph_index, &pis->ctm, ppath, pfont);
  217. }
  218.  
  219. /* Append a simple glyph outline. */
  220. private int
  221. append_simple(const byte *glyph, const gs_matrix_fixed *pmat, gx_path *ppath,
  222.   gs_font_type42 *pfont)
  223. {    int numContours = s16(glyph);
  224.     const byte *pends = glyph + 10;
  225.     const byte *pinstr = pends + numContours * 2;
  226.     const byte *pflags;
  227.     uint npoints;
  228.     const byte *pxc, *pyc;
  229.     int code;
  230.  
  231.     if ( numContours == 0 )
  232.       return 0;
  233.     /*
  234.      * It appears that the only way to find the X and Y coordinate
  235.      * tables is to parse the flags.  If this is true, it is an
  236.      * incredible piece of bad design.
  237.      */
  238.       { const byte *pf = pflags = pinstr + 2 + u16(pinstr);
  239.         uint xbytes = npoints = u16(pinstr - 2) + 1;
  240.         uint np = npoints;
  241.  
  242.         while ( np > 0 )
  243.           { byte flags = *pf++;
  244.         uint reps = (flags & gf_Repeat ? *pf++ + 1 : 1);
  245.         if ( !(flags & gf_xShort) )
  246.           { if ( flags & gf_xSame )
  247.               xbytes -= reps;
  248.             else
  249.               xbytes += reps;
  250.           }
  251.         np -= reps;
  252.           }
  253.         pxc = pf;
  254.         pyc = pxc + xbytes;
  255.       }
  256.  
  257.     /* Interpret the contours. */
  258.  
  259.     { uint i, np;
  260.       gs_fixed_point pt;
  261.       float scale = pfont->data.unitsPerEm;
  262.       uint reps = 0;
  263.       byte flags;
  264.  
  265.       gs_point_transform2fixed(pmat, 0.0, 0.0, &pt);
  266.       for ( i = 0, np = 0; i < numContours; ++i )
  267.         { bool move = true;
  268.           uint last_point = u16(pends + i * 2);
  269.           float dx, dy;
  270.           int off_curve = 0;
  271.           gs_fixed_point start;
  272.           gs_fixed_point cpoints[3];
  273.  
  274.           for ( ; np <= last_point; --reps, ++np )
  275.         { gs_fixed_point dpt;
  276.           if ( reps == 0 )
  277.             { flags = *pflags++;
  278.               reps = (flags & gf_Repeat ? *pflags++ + 1 : 1);
  279.             }
  280.           if ( flags & gf_xShort )
  281.             dx = (flags & gf_xPos ? *pxc++ : -(int)*pxc++) / scale;
  282.           else if ( !(flags & gf_xSame) )
  283.             dx = s16(pxc) / scale, pxc += 2;
  284.           else
  285.             dx = 0;
  286.           if ( flags & gf_yShort )
  287.             dy = (flags & gf_yPos ? *pyc++ : -(int)*pyc++) / scale;
  288.           else if ( !(flags & gf_ySame) )
  289.             dy = s16(pyc) / scale, pyc += 2;
  290.           else
  291.             dy = 0;
  292.           code = gs_distance_transform2fixed(pmat, dx, dy, &dpt);
  293.           if ( code < 0 )
  294.             return code;
  295.           pt.x += dpt.x, pt.y += dpt.y;
  296. #define control1(xy) cpoints[1].xy
  297. #define control2(xy) cpoints[2].xy
  298. #define control3off(xy) ((cpoints[2].xy + pt.xy) / 2)
  299.           if ( move )
  300.             { if_debug2('1', "[1t]start (%g,%g)\n",
  301.                 fixed2float(pt.x), fixed2float(pt.y));
  302.               start = pt;
  303.               code = gx_path_add_point(ppath, pt.x, pt.y);
  304.               cpoints[0] = pt;
  305.               move = false;
  306.             }
  307.           else if ( flags & gf_OnCurve )
  308.             { if_debug2('1', "[1t]ON (%g,%g)\n",
  309.                 fixed2float(pt.x), fixed2float(pt.y));
  310.               if ( off_curve )
  311.             code = gx_path_add_curve(ppath, control1(x),
  312.                          control1(y), control2(x),
  313.                          control2(y), pt.x, pt.y);
  314.               else
  315.             code = gx_path_add_line(ppath, pt.x, pt.y);
  316.               cpoints[0] = pt;
  317.               off_curve = 0;
  318.             }
  319.           else
  320.             { if_debug2('1', "[1t]...off (%g,%g)\n",
  321.                 fixed2float(pt.x), fixed2float(pt.y));
  322.               switch ( off_curve++ )
  323.             {
  324.             default:        /* >= 2 */
  325.               code = gx_path_add_curve(ppath,
  326.                     control1(x), control1(y),
  327.                     control2(x), control2(y),
  328.                     control3off(x), control3off(y));
  329.               cpoints[0] = cpoints[2];
  330.               off_curve = 1;
  331.               /* falls through */
  332.             case 0:
  333.               cpoints[1] = pt;
  334.               /* falls through */
  335.             case 1:
  336.               cpoints[2] = pt;
  337.             }
  338.             }
  339.           if ( code < 0 )
  340.             return code;
  341.         }
  342.           if ( off_curve )
  343.         code = gx_path_add_curve(ppath, control1(x), control1(y),
  344.                      control2(x), control2(y),
  345.                      start.x, start.y);
  346.           code = gx_path_close_subpath(ppath);
  347.           if ( code < 0 )
  348.         return code;
  349.         }
  350.     }
  351.     return 0;
  352. }
  353.  
  354. /* Append a glyph outline. */
  355. private int
  356. append_outline(uint glyph_index, const gs_matrix_fixed *pmat, gx_path *ppath,
  357.   gs_font_type42 *pfont)
  358. {    gs_const_string glyph_string;
  359. #define glyph glyph_string.data
  360.     int numContours;
  361.     int code;
  362.  
  363.     code = (*pfont->data.get_outline)(pfont, glyph_index, &glyph_string);
  364.     if ( code < 0 )
  365.       return code;
  366.     if ( glyph == 0 )        /* empty glyph */
  367.       return 0;
  368.     numContours = s16(glyph);
  369.     if ( numContours >= 0 )
  370.       return append_simple(glyph, pmat, ppath, pfont);
  371.     if ( numContours != -1 )
  372.       return_error(gs_error_rangecheck);
  373.     /* This is a component glyph.  Things get messy.  */
  374.     { uint flags;
  375.       float scale = pfont->data.unitsPerEm;
  376.  
  377.       glyph += 10;
  378.       do
  379.         { uint comp_index = u16(glyph + 2);
  380.           gs_matrix_fixed mat;
  381.           gs_matrix scale_mat;
  382.  
  383.           flags = u16(glyph);
  384.           glyph += 4;
  385.           mat = *pmat;
  386.           if ( flags & cg_argsAreXYValues )
  387.         { int arg1, arg2;
  388.           gs_fixed_point pt;
  389.           if ( flags & cg_argsAreWords )
  390.             arg1 = s16(glyph), arg2 = s16(glyph + 2), glyph += 4;
  391.           else
  392.             arg1 = glyph[0], arg2 = glyph[1], glyph += 2;
  393.           gs_point_transform2fixed(pmat, arg1 / scale,
  394.                        arg2 / scale, &pt);
  395.           /****** HACK: WE KNOW ABOUT FIXED MATRICES ******/
  396.           mat.tx = fixed2float(mat.tx_fixed = pt.x);
  397.           mat.ty = fixed2float(mat.ty_fixed = pt.y);
  398.         }
  399.           else
  400.         { /****** WE DON'T HANDLE POINT MATCHING YET ******/
  401.           glyph += (flags & cg_argsAreWords ? 4 : 2);
  402.         }
  403. #define s2_14(p) (s16(p) / 16384.0)
  404.           if ( flags & cg_haveScale )
  405.         { scale_mat.xx = scale_mat.yy = s2_14(glyph);
  406.           scale_mat.xy = scale_mat.yx = 0;
  407.           glyph += 2;
  408.         }
  409.           else if ( flags & cg_haveXYScale )
  410.         { scale_mat.xx = s2_14(glyph);
  411.           scale_mat.yy = s2_14(glyph + 2);
  412.           scale_mat.xy = scale_mat.yx = 0;
  413.           glyph += 4;
  414.         }
  415.           else if ( flags & cg_have2x2 )
  416.         { scale_mat.xx = s2_14(glyph);
  417.           scale_mat.xy = s2_14(glyph + 2);
  418.           scale_mat.yx = s2_14(glyph + 4);
  419.           scale_mat.yy = s2_14(glyph + 6);
  420.           glyph += 8;
  421.         }
  422.           else
  423.         goto no_scale;
  424. #undef s2_14
  425.           scale_mat.tx = 0;
  426.           scale_mat.ty = 0;
  427.           /* The scale doesn't affect mat.t{x,y}, so we don't */
  428.           /* need to update the fixed components. */
  429.           gs_matrix_multiply(&scale_mat, (const gs_matrix *)&mat,
  430.                  (gs_matrix *)&mat);
  431. no_scale:     code = append_outline(comp_index, &mat, ppath, pfont);
  432.           if ( code < 0 )
  433.         return code;
  434.         }
  435.       while ( flags & cg_moreComponents );
  436.     }
  437.     return 0;
  438. #undef glyph
  439. }
  440.